<!DOCTYPE html>
<html>
<head hexo-theme='https://volantis.js.org/#'>
  <meta charset="utf-8">
  <!-- SEO相关 -->
  
    
  
  <!-- 渲染优化 -->
  <meta name="renderer" content="webkit">
  <meta name="force-rendering" content="webkit">
  <meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
  <meta name="HandheldFriendly" content="True" >
  <meta name="apple-mobile-web-app-capable" content="yes">
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
  <meta name="baidu-site-verification" content="hZiKlANZ5f" />
  <!-- 页面元数据 -->
  
    <title>计算机网络笔记 - CyChan&#39;s Blog</title>
  
    <meta name="keywords" content="计算机网络">
  
  
    <meta name="description" content="1.POST和GET的区别
GET和POST本质上就是TCP链接，并无差别
GET，它用于获取信息，它只是获取、查询数据，也就是说它不会修改服务器上的数据，从这点来讲，它是数据安全的。例如获取更新的20条微博。
">
  

  <!-- feed -->
  
    <link rel="alternate" href="/atom.xml" title="CyChan's Blog">
  

  <!-- import meta -->
  

  <!-- link -->
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5.13/css/all.min.css">
  
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@3.5.7/dist/jquery.fancybox.min.css">

  
  
    
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/node-waves@0.7.6/dist/waves.min.css">

  

  
  <link rel="shortcut icon" type='image/x-icon' href="https://gitee.com/CyChan811/BlogImage/raw/master/img/头像.jpg">
  

  
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/aplayer@1.10/dist/APlayer.min.css">
  

  

  <!-- import link -->
  

  
  
    
<link rel="stylesheet" href="/css/style.css">

  

  <script>
    function setLoadingBarProgress(num) {
      document.getElementById('loading-bar').style.width=num+"%";
    }
  </script>

  
  
</head>

<body>
  
  <div id="loading-bar-wrapper">
  <div id="loading-bar"></div>
</div>
<header class="l_header shadow blur">
  <div class='container'>
  <div class='wrapper'>
    <div class='nav-sub'>
      <p class="title"></p>
      <ul class='switcher nav-list-h'>
        <li><a class="s-comment fas fa-comments fa-fw" target="_self" href='javascript:void(0)'></a></li>
        
          <li><a class="s-toc fas fa-list fa-fw" target="_self" href='javascript:void(0)'></a></li>
        
      </ul>
    </div>
		<div class="nav-main">
      
        
        <a class="title flat-box" target="_self" href='/'>
          
          
          
            CyChan
          
          
        </a>
      

			<div class='menu navigation'>
				<ul class='nav-list-h'>
          
          
          
            
            
              <li>
                <a class="flat-box" href=/
                  
                  
                  
                    id="home"
                  >
                  <i class='fas fa-home fa-fw'></i>首页
                </a>
                
              </li>
            
          
          
            
            
              <li>
                <a class="flat-box" href=/categories/
                  
                  
                  
                    id="categories"
                  >
                  <i class='fas fa-folder-open fa-fw'></i>分类
                </a>
                
              </li>
            
          
          
            
            
              <li>
                <a class="flat-box" href=/tags/
                  
                  
                  
                    id="tags"
                  >
                  <i class='fas fa-tags fa-fw'></i>标签
                </a>
                
              </li>
            
          
          
            
            
              <li>
                <a class="flat-box" href=/archives/
                  
                  
                  
                    id="archives"
                  >
                  <i class='fas fa-archive fa-fw'></i>归档
                </a>
                
              </li>
            
          
          
            
            
              <li>
                <a class="flat-box" href=/friends/
                  
                  
                  
                    id="friends"
                  >
                  <i class='fas fa-link fa-fw'></i>友链
                </a>
                
              </li>
            
          
          
            
            
              <li>
                <a class="flat-box" href=/Message/
                  
                  
                  
                    id="Message"
                  >
                  <i class='fas fa-comments fa-fw fa-fw'></i>留言板
                </a>
                
              </li>
            
          
          
            
            
              <li>
                <a class="flat-box" href=/about/
                  
                  
                  
                    id="about"
                  >
                  <i class='fas fa-info-circle fa-fw'></i>关于
                </a>
                
              </li>
            
          
          
				</ul>
			</div>

      <div class="m_search">
        <form name="searchform" class="form u-search-form">
          <i class="icon fas fa-search fa-fw"></i>
          <input type="text" class="input u-search-input" placeholder="Search..." />
        </form>
      </div>

			<ul class='switcher nav-list-h'>
				
					<li><a class="s-search fas fa-search fa-fw" target="_self" href='javascript:void(0)'></a></li>
				
				<li>
          <a class="s-menu fas fa-bars fa-fw" target="_self" href='javascript:void(0)'></a>
          <ul class="menu-phone list-v navigation white-box">
            
              
            
              <li>
                <a class="flat-box" href=/
                  
                  
                  
                    id="home"
                  >
                  <i class='fas fa-home fa-fw'></i>首页
                </a>
                
              </li>
            
          
            
              
            
              <li>
                <a class="flat-box" href=/categories/
                  
                  
                  
                    id="categories"
                  >
                  <i class='fas fa-folder-open fa-fw'></i>分类
                </a>
                
              </li>
            
          
            
              
            
              <li>
                <a class="flat-box" href=/tags/
                  
                  
                  
                    id="tags"
                  >
                  <i class='fas fa-tags fa-fw'></i>标签
                </a>
                
              </li>
            
          
            
              
            
              <li>
                <a class="flat-box" href=/archives/
                  
                  
                  
                    id="archives"
                  >
                  <i class='fas fa-archive fa-fw'></i>归档
                </a>
                
              </li>
            
          
            
              
            
              <li>
                <a class="flat-box" href=/friends/
                  
                  
                  
                    id="friends"
                  >
                  <i class='fas fa-link fa-fw'></i>友链
                </a>
                
              </li>
            
          
            
              
            
              <li>
                <a class="flat-box" href=/Message/
                  
                  
                  
                    id="Message"
                  >
                  <i class='fas fa-comments fa-fw fa-fw'></i>留言板
                </a>
                
              </li>
            
          
            
              
            
              <li>
                <a class="flat-box" href=/about/
                  
                  
                  
                    id="about"
                  >
                  <i class='fas fa-info-circle fa-fw'></i>关于
                </a>
                
              </li>
            
          
            
          </ul>
        </li>
			</ul>
		</div>
	</div>
  </div>
</header>

<script>setLoadingBarProgress(40);</script>



  <div class="l_body nocover">
    <div class='body-wrapper'>
      

<div class='l_main'>
  

  
    <article id="post" class="post white-box reveal shadow article-type-post" itemscope itemprop="blogPost">
      


  <section class='meta'>
    
      
      
      <div class="meta" id="header-meta">
        
          
  <h1 class="title">
    <a href="/2021/01/31/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C%E7%AC%94%E8%AE%B0/">
      计算机网络笔记
    </a>
  </h1>


        
        <div class='new-meta-box'>
          
            
          
            
              
<div class='new-meta-item author'>
  <a href="https://cychan811.gitee.io" rel="nofollow">
    <img src="https://gitee.com/CyChan811/BlogImage/raw/master/img/头像.jpg">
    <p>CyChan</p>
  </a>
</div>

            
          
            
              
  
  <div class='new-meta-item category'>
    <a href='/categories/%E5%90%8E%E5%8F%B0/' rel="nofollow">
      <i class="fas fa-folder-open fa-fw" aria-hidden="true"></i>
      <p>后台</p>
    </a>
  </div>


            
          
            
              <div class="new-meta-item date">
  <a class='notlink'>
    <i class="fas fa-calendar-alt fa-fw" aria-hidden="true"></i>
    <p>发布于：2021年1月31日</p>
  </a>
</div>

            
          
            
              

            
          
            
              
  <div class="new-meta-item browse valine">
    <a class='notlink'>
      <i class="fas fa-eye fa-fw" aria-hidden="true"></i>
      
      <span id="/2021/01/31/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C%E7%AC%94%E8%AE%B0/" class="leancloud_visitors" data-flag-title="计算机网络笔记">
      <p>
        <span class="leancloud-visitors-count"></span>
      </p>
      </span>
    </a>
  </div>


            
          
        </div>
        
          <hr>
        
      </div>
    
  </section>


      <section class="article typo">
        <div class="article-entry" itemprop="articleBody">
          
          
          <h2 id="1-POST和GET的区别"><a href="#1-POST和GET的区别" class="headerlink" title="1.POST和GET的区别"></a>1.POST和GET的区别</h2><ol>
<li>GET和POST本质上就是TCP链接，并无差别</li>
<li><strong>GET，它用于获取信息，它只是获取、查询数据，也就是说它不会修改服务器上的数据</strong>，从这点来讲，它是<strong>数据安全的</strong>。例如获取更新的20条微博。</li>
</ol>
<a id="more"></a>

<ol start="2">
<li><strong>Post，向指定的资源提交要被处理的数据，它是可以向服务器发送修改请求，从而修改服务器的</strong>，比如微博的点赞、评论操作，这就要用到Post了，当然它也是可以仅仅获取数据的。由于它可以修改服务器数据，所以这是<strong>数据不安全的</strong>。</li>
<li>GET后退按钮/刷新无害，POST数据会被重新提交（浏览器应该告知用户数据会被重新提交）。</li>
<li>GET书签可收藏，POST为书签不可收藏。</li>
<li>GET能被缓存，POST不能缓存 。</li>
<li>GET编码类型application/x-www-form-url，POST编码类型encodedapplication/x-www-form-urlencoded 或 multipart/form-data。为二进制数据使用多重编码。</li>
<li>GET历史参数保留在浏览器历史中。POST参数不会保存在浏览器历史中。</li>
<li>GET对数据长度有限制，当发送数据时，GET 方法向 URL 添加数据；URL 的长度是受限制的（URL 的最大长度是 2048 个字符）。POST无限制。<strong>url 长度限制是某些浏览器和服务器的限制，和 HTTP 协议没有关系。</strong></li>
<li>GET只允许 ASCII 字符。POST没有限制。也允许二进制数据。</li>
<li>与 POST 相比，GET 的安全性较差，因为所发送的数据是 URL 的一部分。在发送密码或其他敏感信息时绝不要使用 GET ！POST 比 GET 更安全，因为参数不会被保存在浏览器历史或 web 服务器日志中。<strong>当然这只是相对安全，从传输的角度来说，他们都是不安全的，因为HTTP在网络上都是明文传输的，只要在网络节点上捉包，就能完整的获取数据报文。想要安全的传输，就只有加密，使用HTTPS。</strong></li>
<li>GET的数据在 URL 中对所有人都是可见的。POST的数据不会显示在 URL 中。</li>
<li><strong>在带参数的报文中，Get方法的参数应该放在url中，其报文主体没有任何语义，Post方法的请求数据（参数）则放在报文主体中。</strong></li>
</ol>
<h2 id="2-高性能网络通信库中为何要将侦听-socket-设置成非阻塞的？"><a href="#2-高性能网络通信库中为何要将侦听-socket-设置成非阻塞的？" class="headerlink" title="2.高性能网络通信库中为何要将侦听 socket 设置成非阻塞的？"></a>2.高性能网络通信库中为何要将侦听 socket 设置成非阻塞的？</h2><p>我们知道如果需要使用 IO 复用函数统一管理各个 fd，需要将 clientfd 设置成非阻塞的，那么listenfd一定要设置成非阻塞的吗？答案是不一定的——只要不用IO复用函数去管理listenfd就可以了，listenfd 如果不设置成非阻塞的，那么accept函数在没有新连接时就会阻塞。</p>
<p><strong>具体→</strong><a href="https://my.oschina.net/balloonwj/blog/4403535/print" target="_blank" rel="noopener">https://my.oschina.net/balloonwj/blog/4403535/print</a></p>
<h2 id="3-UDP-与-TCP-比较"><a href="#3-UDP-与-TCP-比较" class="headerlink" title="3.UDP 与 TCP 比较"></a>3.UDP 与 TCP 比较</h2><h4 id="TCP："><a href="#TCP：" class="headerlink" title="TCP："></a>TCP：</h4><p>为应用层提供可靠的、面向连接的和基于流的服务。使用超时重传、数据确认等方式来确保数据包被正确地发送至目的端，因此服务是可靠的。</p>
<h4 id="UDP："><a href="#UDP：" class="headerlink" title="UDP："></a>UDP：</h4><p>则与TCP想反，它为应用层提供不可靠、无连接和基于数据报的服务。“不可靠”意味着UDP协议无法保证数据从发送端正确地传送到目的端。如果数据在途中丢失，或者目的端通过数据校验发现数据错误而将其丢弃，则UDP协议只是简单地通知应用程序发送失败。</p>
<h4 id="什么时候该使用TCP："><a href="#什么时候该使用TCP：" class="headerlink" title="什么时候该使用TCP："></a>什么时候该使用TCP：</h4><p>当对网络通讯质量有要求的时候，比如：整个数据要准确无误的传递给对方，这往往用于一些要求可靠的应用，</p>
<h4 id="什么时候使用UDP："><a href="#什么时候使用UDP：" class="headerlink" title="什么时候使用UDP："></a>什么时候使用UDP：</h4><p>当对网络通讯质量要求不高的时候，要求速度尽可能的快，这时就可以使用UDP。</p>
<h2 id="4-TCP可靠传输原理"><a href="#4-TCP可靠传输原理" class="headerlink" title="4.TCP可靠传输原理"></a>4.TCP可靠传输原理</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">ARQ（Automatic Repeat-reQuest）（自动重传请求）</span><br><span class="line"></span><br><span class="line">- 停止等待ARQ协议</span><br><span class="line"></span><br><span class="line">- 连续ARQ协议</span><br></pre></td></tr></table></figure>
<h3 id="停止等待ARQ协议"><a href="#停止等待ARQ协议" class="headerlink" title="停止等待ARQ协议"></a>停止等待ARQ协议</h3><p>全双工通信的双发既是发送方也是接收方。下面为了讨论问题的方便，我们仅考虑A发送数据而B接受数据并发送确认。因此A就做发送方，B叫做接收方。因为这里是讨论可靠传输的原理，因此把传送的数据单元都称为分组，而并不考虑数据在哪一层次上传送的。停止等待就是每发送完一个分组就停止发送，等待对方的确认。在收到确认后在发送下一个分组。</p>
<h4 id="1-无差错情况"><a href="#1-无差错情况" class="headerlink" title="1. 无差错情况"></a>1. 无差错情况</h4><p>A发送分组M1，发送完就暂停发送，等待B的确认。B收到M1就向A发送确认。A在收到了对M1的确认后，就再发送下一个分组M2<br><img src="http://static.oschina.net/uploads/space/2014/0828/210548_wB7l_1469576.png" alt=""></p>
<h4 id="2-出现差错"><a href="#2-出现差错" class="headerlink" title="2. 出现差错"></a>2. 出现差错</h4><p>如果A发送的过程中出现差错，B在接收M1时检测出了差错，就丢弃M1，其他什么都不做（也不会通知A收到有差错的分组）。又或者A传送的过程中分组丢失了，以上这两种情况下，B不会发送任何信息。</p>
<p>超时重传的原理也很简单：发送方发送完一个分组后，就会设置一个超时计时器，如果超时计时器到期之前没有收到接收方发来的确认信息，则会重发刚发送过的分组；如果收到确认信息，则撤销该超时计时器。<br><img src="http://static.oschina.net/uploads/space/2014/0828/210708_FIdK_1469576.png" alt=""></p>
<p>这里应该注意的是：</p>
<ol>
<li>既然发送方发送的分组可能丢失或者有差错，可能需要重传，那么它必须暂时保留已发送的分组副本，只有收到确认后，才清除这个副本。</li>
<li>分组和确认分组信息都应该有各自的编号，用来标示每一个分组和确认信息。（这样才知道需要发送哪个分组，收到了哪个分组的确认信息）</li>
<li>超时计时器设置的时间应该略长于分组传送往返时间</li>
</ol>
<h4 id="3-确认丢失和确认迟到"><a href="#3-确认丢失和确认迟到" class="headerlink" title="3. 确认丢失和确认迟到"></a>3. 确认丢失和确认迟到</h4><p><img src="http://static.oschina.net/uploads/space/2014/0828/210836_X9ia_1469576.png" alt=""></p>
<p>像上述这种可靠传输协议常称为<strong>自动重传请求ARQ (Automatic Repeat reQuest)，ARQ 表明重传的请求是自动进行的。接收方不需要请求发送方重传某个出错的分组 。</strong></p>
<h3 id="流水线传输"><a href="#流水线传输" class="headerlink" title="流水线传输"></a>流水线传输</h3><p>这种停止等待协议的优点是简单，但缺点是信道利用率太低，传输效率不高。</p>
<h4 id="流水线传输："><a href="#流水线传输：" class="headerlink" title="流水线传输："></a>流水线传输：</h4><ul>
<li><strong>发送方可连续发送多个分组，不必每发完一个分组就停顿下来等待对方的确认。</strong></li>
<li>由于信道上一直有数据不间断地传送，这种传输方式可获得很高的信道利用率。</li>
</ul>
<p><img src="http://static.oschina.net/uploads/space/2014/0828/212142_4RTX_1469576.png" alt=""><br>当使用流水线传输时，就要使用下面介绍的连续ARQ协议和滑动窗口协议。</p>
<h3 id="连续-ARQ-协议"><a href="#连续-ARQ-协议" class="headerlink" title="连续 ARQ 协议"></a>连续 ARQ 协议</h3><p>下图表示发送方维持的发送窗口，<strong>他的意义是：位于发送窗口内的5个分组都可以连续发送出去，而不需要等待对方的确认</strong>。这样信道利用率就提高了。<br><img src="http://static.oschina.net/uploads/space/2014/0829/133646_3LGX_1469576.png" alt=""><br>连续ARQ协议规定，发送方每接收到一个确认，就把发送窗口向前滑动一个分组的位置。下图表示发送方收到了第一个分组的确认，于是把发送窗口向前移动一个分组的位置。</p>
<p>如果原来已经发送了前5个分组，那么现在就可以发送窗口内的第六个分组。<br><img src="http://static.oschina.net/uploads/space/2014/0829/140541_7TnN_1469576.png" alt=""><br>接收方一般都采用<strong>累积确认</strong>的方式。这就是说接收方不必对收到的分组逐个发送确认，而是可以在几个分组后，对按序到达的最后一个分组发送确认，这样就表示：到这个分组为止的所有分组都已经正确接收到了。</p>
<h3 id="累积确认"><a href="#累积确认" class="headerlink" title="累积确认"></a>累积确认</h3><ul>
<li>接收方一般采用累积确认的方式。即不必对收到的分组逐个发送确认，<strong>而是对按序到达的最后一个分组发送确认</strong>，这样就表示：到这个分组为止的所有分组都已正确收到了。</li>
<li>累积确认有的优点是：容易实现，即使确认丢失也不必重传。缺点是：不能向发送方反映出接收方已经正确收到的所有分组的信息。</li>
</ul>
<h3 id="Go-back-N（回退-N）"><a href="#Go-back-N（回退-N）" class="headerlink" title="Go-back-N（回退 N）"></a>Go-back-N（回退 N）</h3><ul>
<li>如果发送方发送了前5个分组，而中间的第3个分组丢失了。这时接收方只能对前两个分组发出确认。发送方无法知道后面三个分组的下落，而只好把后面的三个分组都再重传一次。</li>
<li>这就叫做 Go-back-N（回退N），表示需要再退回来重传已发送过的 N 个分组。</li>
<li>可见当通信线路质量不好时，连续 ARQ 协议会带来负面的影响。</li>
</ul>
<h2 id="5-TCP-拥塞控制的作用，理解具体原理"><a href="#5-TCP-拥塞控制的作用，理解具体原理" class="headerlink" title="5.TCP 拥塞控制的作用，理解具体原理"></a>5.TCP 拥塞控制的作用，理解具体原理</h2><h4 id="拥塞控制："><a href="#拥塞控制：" class="headerlink" title="拥塞控制："></a>拥塞控制：</h4><p>防止过多的数据注入到网络当中，这样可以使网络中的路由器或链路不致过载。（通过拥塞窗口处理网络拥塞现象的一种机制）</p>
<h4 id="拥塞控制过程（Reno算法）"><a href="#拥塞控制过程（Reno算法）" class="headerlink" title="拥塞控制过程（Reno算法）"></a>拥塞控制过程（Reno算法）</h4><p>将拥塞控制的过程分为四个阶段：<strong>慢启动、拥塞避免、快重传和快恢复</strong></p>
<ul>
<li>慢启动阶段思路是不要一开始就发送大量的数据，先探测一下网络的拥塞程度，也就是说由小到大逐渐增加拥塞窗口的大小，在没有出现丢包时每收到一个 ACK 就将拥塞窗口大小加一（单位是 MSS，最大单个报文段长度），每轮次发送窗口增加一倍，呈指数增长，若出现丢包，则将拥塞窗口减半，进入拥塞避免阶段；</li>
<li>当窗口达到慢启动阈值或出现丢包时，进入拥塞避免阶段，窗口每轮次加一，呈线性增长；当收到对一个报文的三个重复的 ACK 时，认为这个报文的下一个报文丢失了，进入快重传阶段，要求接收方在收到一个失序的报文段后就立即发出重复确认（为的是使发送方及早知道有报文段没有到达对方，可提高网络吞吐量约20%）而不要等到自己发送数据时捎带确认；</li>
<li>快重传完成后进入快恢复阶段，<strong>将慢启动阈值修改为当前拥塞窗口值的一半</strong>，同时拥塞窗口值等于慢启动阈值，然后进入拥塞避免阶段，重复上述过程。<br><img src="https://img-blog.csdn.net/20180420160407836" alt=""></li>
</ul>
<h2 id="6-理解三次握手以及四次挥手具体过程，三次握手的原因、四次挥手原因"><a href="#6-理解三次握手以及四次挥手具体过程，三次握手的原因、四次挥手原因" class="headerlink" title="6.理解三次握手以及四次挥手具体过程，三次握手的原因、四次挥手原因"></a>6.理解三次握手以及四次挥手具体过程，三次握手的原因、四次挥手原因</h2><h4 id="三次握手过程理解："><a href="#三次握手过程理解：" class="headerlink" title="三次握手过程理解："></a>三次握手过程理解：</h4><p><img src="https://gitee.com/CyChan811/BlogImage/raw/master/img/20200731004808.png" alt=""></p>
<ul>
<li>标志位<ul>
<li>SYN：请求建立连接</li>
<li>ACK：应答</li>
<li>FIN：断开连接</li>
</ul>
</li>
</ul>
<p>第一次握手：建立连接时，客户端发送syn包（syn=j）到服务器，并进入SYN_SENT状态，等待服务器确认；SYN：同步序列编号（Synchronize Sequence Numbers）。</p>
<p>第二次握手：服务器收到syn包，必须确认客户的SYN（ack=j+1），同时自己也发送一个SYN包（syn=k），即SYN+ACK包，此时服务器进入SYN_RECV状态；</p>
<p>第三次握手：客户端收到服务器的SYN+ACK包，向服务器发送确认包ACK(ack=k+1），此包发送完毕，客户端和服务器进入ESTABLISHED（TCP连接成功）状态，完成三次握手。</p>
<h4 id="四次挥手过程理解："><a href="#四次挥手过程理解：" class="headerlink" title="四次挥手过程理解："></a>四次挥手过程理解：</h4><p>1.哪一端断开连接都可以<br><img src="https://gitee.com/CyChan811/BlogImage/raw/master/img/20200731004908.png" alt=""></p>
<ol>
<li>客户端进程发出连接释放报文，并且停止发送数据。释放数据报文首部，FIN=1，其序列号为seq=u（等于前面已经传送过来的数据的最后一个字节的序号加1），此时，客户端进入FIN-WAIT-1（终止等待1）状态。 TCP规定，FIN报文段即使不携带数据，也要消耗一个序号。</li>
<li>服务器收到连接释放报文，发出确认报文，ACK=1，ack=u+1，并且带上自己的序列号seq=v，此时，服务端就进入了CLOSE-WAIT（关闭等待）状态。TCP服务器通知高层的应用进程，客户端向服务器的方向就释放了，这时候处于半关闭状态，即客户端已经没有数据要发送了，但是服务器若发送数据，客户端依然要接受。这个状态还要持续一段时间，也就是整个CLOSE-WAIT状态持续的时间。</li>
<li>客户端收到服务器的确认请求后，此时，客户端就进入FIN-WAIT-2（终止等待2）状态，等待服务器发送连接释放报文（在这之前还需要接受服务器发送的最后的数据）。</li>
<li>服务器将最后的数据发送完毕后，就向客户端发送连接释放报文，FIN=1，ack=u+1，由于在半关闭状态，服务器很可能又发送了一些数据，假定此时的序列号为seq=w，此时，服务器就进入了LAST-ACK（最后确认）状态，等待客户端的确认。</li>
<li>客户端收到服务器的连接释放报文后，必须发出确认，ACK=1，ack=w+1，而自己的序列号是seq=u+1，此时，客户端就进入了TIME-WAIT（时间等待）状态。注意此时TCP连接还没有释放，必须经过2MSL（最长报文段寿命）的时间后，当客户端撤销相应的TCB后，才进入CLOSED状态。</li>
<li>服务器只要收到了客户端发出的确认，立即进入CLOSED状态。同样，撤销TCB后，就结束了这次的TCP连接。可以看到，服务器结束TCP连接的时间要比客户端早一些。</li>
</ol>
<h4 id="常见面试题"><a href="#常见面试题" class="headerlink" title="常见面试题"></a>常见面试题</h4><p><strong>【问题1】为什么连接的时候是三次握手，关闭的时候却是四次握手？</strong></p>
<p>答：因为当Server端收到Client端的SYN连接请求报文后，可以直接发送SYN+ACK报文。其中ACK报文是用来应答的，SYN报文是用来同步的。但是关闭连接时，当Server端收到FIN报文时，很可能并不会立即关闭SOCKET，所以只能先回复一个ACK报文，告诉Client端，”你发的FIN报文我收到了”。只有等到我Server端所有的报文都发送完了，我才能发送FIN报文，因此不能一起发送。故需要四步握手。</p>
<p><strong>【问题2】为什么TIME_WAIT状态需要经过2MSL(最大报文段生存时间)才能返回到CLOSE状态？</strong></p>
<p>答：虽然按道理，四个报文都发送完毕，我们可以直接进入CLOSE状态了，但是我们必须假象网络是不可靠的，有可以最后一个ACK丢失。所以TIME_WAIT状态就是用来重发可能丢失的ACK报文。在Client发送出最后的ACK回复，但该ACK可能丢失。Server如果没有收到ACK，将不断重复发送FIN片段。所以Client不能立即关闭，它必须确认Server接收到了该ACK。Client会在发送出ACK之后进入到TIME_WAIT状态。Client会设置一个计时器，等待2MSL的时间。如果在该时间内再次收到FIN，那么Client会重发ACK并再次等待2MSL。所谓的2MSL是两倍的MSL(Maximum Segment Lifetime)。MSL指一个片段在网络中最大的存活时间，2MSL就是一个发送和一个回复所需的最大时间（Linux下MSL是30s）。如果直到2MSL，Client都没有再次收到FIN，那么Client推断ACK已经被成功接收，则结束TCP连接。</p>
<p><strong>【问题3】为什么不能用两次握手进行连接？</strong></p>
<p>答：<br>3次握手完成两个重要的功能，既要双方做好发送数据的准备工作(双方都知道彼此已准备好)，也要允许双方就初始序列号进行协商，这个序列号在握手过程中被发送和确认。<br>现在把三次握手改成仅需要两次握手，死锁是可能发生的。作为例子，考虑计算机S和C之间的通信，假定C给S发送一个连接请求分组，S收到了这个分组，并发 送了确认应答分组。按照两次握手的协定，S认为连接已经成功地建立了，可以开始发送数据分组。可是，C在S的应答分组在传输中被丢失的情况下，将不知道S 是否已准备好，不知道S建立什么样的序列号，C甚至怀疑S是否收到自己的连接请求分组。在这种情况下，C认为连接还未建立成功，将忽略S发来的任何数据分 组，只等待连接确认应答分组。而S在发出的分组超时后，重复发送同样的分组。这样就形成了死锁。</p>
<p><strong>【问题4】如果已经建立了连接，但是客户端突然出现故障了怎么办？</strong></p>
<p>TCP还设有一个保活计时器，显然，客户端如果出现故障，服务器不能一直等下去，白白浪费资源。服务器每收到一次客户端的请求后都会重新复位这个计时器，时间通常是设置为2小时，若两小时还没有收到客户端的任何数据，服务器就会发送一个探测报文段，以后每隔75秒钟发送一次。若一连发送10个探测报文仍然没反应，服务器就认为客户端出了故障，接着就关闭连接。</p>
<h2 id="7-TIME-WAIT的作用"><a href="#7-TIME-WAIT的作用" class="headerlink" title="7.TIME_WAIT的作用"></a>7.TIME_WAIT的作用</h2><ul>
<li>确保最后一个确认报文能够到达。如果没能到达，服务端就会重发FIN请求释放连接。等待一段时间没有收到重发就说明服务的已经CLOSE了。如果有重发，则客户端再发送一次LAST ack信号</li>
<li>等待一段时间是为了让本连接持续时间内所产生的所有报文都从网络中消失，使得下一个新的连接不会出现旧的连接请求报文。我们都知道的是time_wait太短或者取消，可能会使上一个连接延迟的数据包被新的连接收到，从而影响到新连接的数据。</li>
</ul>
<p>在linux中，time_wait时间定死了为1分钟，也就是2MSL，这个时间会保证延迟的数据包在网络中消失，也会保证没有丢失的数据包在这个时间内到达指定端，所以在这个时间后不会存在上一个连接的数据包被新的连接收到的情况了。</p>
<p>TCP必须防止来自之前那个连接的老的重复分组在新连接上出现。为了做到这一点，<strong>TCP将不复用处于TIME_WAIT状态的连接。</strong></p>
<h2 id="8-HTTP协议"><a href="#8-HTTP协议" class="headerlink" title="8.HTTP协议"></a>8.HTTP协议</h2><p>HTTP协议是<strong>超文本传输协议</strong>的缩写，英文是Hyper Text Transfer Protocol。它是从WEB服务器传输超文本标记语言(HTML)到本地浏览器的传送协议。</p>
<p>HTTP是一个<strong>基于TCP/IP通信协议来传递数据的协议</strong>，传输的数据类型为HTML 文件,、图片文件, 查询结果等。</p>
<p>HTTP协议一般用于B/S架构（）。浏览器作为HTTP客户端通过URL向HTTP服务端即WEB服务器发送所有请求。</p>
<h4 id="HTTP特点"><a href="#HTTP特点" class="headerlink" title="HTTP特点"></a>HTTP特点</h4><ol>
<li>http协议支持客户端/服务端模式，也是一种请求/响应模式的协议。</li>
<li>简单快速：客户向服务器请求服务时，只需传送请求方法和路径。请求方法常用的有GET、HEAD、POST。</li>
<li>灵活：HTTP允许传输任意类型的数据对象。传输的类型由Content-Type加以标记。</li>
<li>无连接：限制每次连接只处理一个请求。服务器处理完请求，并收到客户的应答后，即断开连接，但是却不利于客户端与服务器保持会话连接，为了弥补这种不足，产生了两项记录http状态的技术，一个叫做Cookie,一个叫做Session。</li>
<li>无状态：HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息，则它必须重传，这样可能导致每次连接传送的数据量增大。另一方面，在服务器不需要先前信息时它的应答就较快。</li>
</ol>
<p>更多：</p>
<p><a href="https://www.cnblogs.com/an-wen/p/11180076.html" target="_blank" rel="noopener">https://www.cnblogs.com/an-wen/p/11180076.html</a></p>
<p><a href="https://www.cnblogs.com/ranyonsue/p/5984001.html" target="_blank" rel="noopener">https://www.cnblogs.com/ranyonsue/p/5984001.html</a></p>
<h2 id="9-HTTPS协议"><a href="#9-HTTPS协议" class="headerlink" title="9.HTTPS协议"></a>9.HTTPS协议</h2><h4 id="一般http中存在如下问题："><a href="#一般http中存在如下问题：" class="headerlink" title="一般http中存在如下问题："></a>一般http中存在如下问题：</h4><ul>
<li>请求信息明文传输，容易被窃听截取。</li>
<li>数据的完整性未校验，容易被篡改</li>
<li>没有验证对方身份，存在冒充危险</li>
</ul>
<h4 id="什么是HTTPS？"><a href="#什么是HTTPS？" class="headerlink" title="什么是HTTPS？"></a>什么是HTTPS？</h4><p>HTTPS 协议（HyperText Transfer Protocol over Secure Socket Layer）：一般理解为HTTP+SSL/TLS，通过 SSL证书来验证服务器的身份，并为浏览器和服务器之间的通信进行加密。</p>
<h4 id="浏览器在使用HTTPS传输数据的流程是什么？"><a href="#浏览器在使用HTTPS传输数据的流程是什么？" class="headerlink" title="浏览器在使用HTTPS传输数据的流程是什么？"></a>浏览器在使用HTTPS传输数据的流程是什么？</h4><ol>
<li>在百度服务器端首先生成一个秘钥对 -&gt; 对公钥分发</li>
<li>百度将公钥给到了CA认证机构, ca用私钥进行签名 -&gt; 生成了证书.</li>
<li>第一步第二步只做一次</li>
<li>客户端访问百度, 百度将ca生成的证书发送给客户端</li>
<li>浏览器对收到的证书进行认证</li>
<li>如果证书没有问题 -&gt; 使用ca的公钥将服务器的公钥从证书中取出</li>
<li>我们得到了百度的公钥</li>
<li>在浏览器端生成一个随机数, 使用得到的公钥进行加密, 发送给服务器</li>
<li>服务器端使用私钥解密, 得到了随机数, 这个随机数就是对称加密的秘钥</li>
<li>现在秘钥分发已经完成, 后边的通信使用的的对称加密的方式<br><img src="https://pic4.zhimg.com/v2-a994fbf3094d737814fe01c2b919477b_r.jpg" alt=""></li>
</ol>
<h2 id="10-epoll中et和lt的区别与实现原理（重要）"><a href="#10-epoll中et和lt的区别与实现原理（重要）" class="headerlink" title="10.epoll中et和lt的区别与实现原理（重要）"></a>10.epoll中et和lt的区别与实现原理（重要）</h2><p>(1) epoll 两种工作模式</p>
<p><strong>水平触发：</strong><br>内核中的socket接收缓冲区不为空，有<strong>数据可读，读事件一直触发</strong>；内核中的socket<strong>发送缓冲区不满</strong>，可以继续写入数据，写事件<strong>一直触发</strong></p>
<p><strong>边缘触发</strong>：内核中socket接收缓冲区<strong>由空变为不为空，数据由不可读变为可读，事件触发（仅一次）</strong>。<br>内核中socket发送缓冲区<strong>由满变为不满，数据由不可写变为可写，事件触发（仅一次）。</strong></p>
<p>(2) 工作模式选择时候，<strong>LT模式会一直触发可读可写事件，导致效率比较低。ET模式由于读写事件仅通知一次，可能会存在数据丢失的可能。</strong></p>
<p>(3) </p>
<ol>
<li>ET模式时，当有多个连接同时到达服务器，epoll_wait会返回多个描述符，由于在ET模式下就绪状态只返回一次， 因此为了防止漏掉连接，需要循环调用accept直到接收全部连接（即返回EAGAIN错误）。</li>
<li>ET模式时，在读写数据时，同样需要注意读写事件只触发一次的问题，若一次读或写没有处理全部数据， 则会导致数据丢失。解决办法是，accept接收连接时，设置连接的套接字为非阻塞， 并在读写数据时<strong>循环调用</strong>read/write直到数据全部处理为止（即返回EAGAIN错误）。</li>
<li>LT模式时，若监控epoll    out事件，由于内核缓冲区一开始时一直处于可写状态，会导致epoll_wait一直返回，降低效率。解决办法，<br>一开始不监听out事件，直接写数据直到写缓冲区满时（即返回EAGAIN错误），再监听out事件，当数据全部写完时，就取消对out事件的监听</li>
</ol>
<h2 id="11-服务器端怎么判断客户端已断开连接"><a href="#11-服务器端怎么判断客户端已断开连接" class="headerlink" title="11.服务器端怎么判断客户端已断开连接"></a>11.服务器端怎么判断客户端已断开连接</h2><ol>
<li>（tcp内部机制）TCP的KeepAlive保活机制，它会先要求此连接一定时间没有活动（一般是几个小时），然后发出数据段，经过多次尝试后（每次尝试之间也有时间间隔），如果仍没有响应，则判断连接中断。可想而知，整个周期需要很长的时间。</li>
<li>（应用层实现）一个简单的heart-beat实现一般测试连接是否中断采用的时间间隔都比较短，可以很快的决定连接是否中断。并且，由于是在应用层实现，因为可以自行决定当判断连接中断后应该采取的行为，而keepalive在判断连接失败后只会将连接丢弃。</li>
</ol>
<h2 id="12-TTL是什么？有什么用处"><a href="#12-TTL是什么？有什么用处" class="headerlink" title="12.TTL是什么？有什么用处"></a>12.TTL是什么？有什么用处</h2><p>TTL是Time To Live，一般是hup count，每经过一个路由就会被减去一，如果它变成0，包会被丢掉。它的主要目的是防止包在有回路的网络上死转，浪费网络资源。</p>
<h2 id="13-网络编程的一般步骤"><a href="#13-网络编程的一般步骤" class="headerlink" title="13.网络编程的一般步骤"></a>13.网络编程的一般步骤</h2><h4 id="TCP连接"><a href="#TCP连接" class="headerlink" title="TCP连接"></a>TCP连接</h4><ol>
<li>服务器端1）创建套接字socket；2）绑定端口号bind；3）监听连接listen；4）接受连接请求accept，并返回新的套接字；5）用新返回的套接字recv/send；6）关闭套接字。</li>
<li>客户端1）创建套接字socket; 2）发起建立连接请求connect; 3）发送/接收数据send/recv；4）关闭套接字。</li>
</ol>
<h4 id="UDP连接"><a href="#UDP连接" class="headerlink" title="UDP连接"></a>UDP连接</h4><ol>
<li>服务器端:1）创建套接字socket；2）绑定端口号bind；3）接收/发送消息recvfrom/sendto；4）关闭套接字。</li>
<li>客户端:1）创建套接字socket；2）发送/接收消息sendto/recvfrom；3）关闭套接字.</li>
</ol>
<h2 id="14-cookie和session的区别？"><a href="#14-cookie和session的区别？" class="headerlink" title="14.cookie和session的区别？"></a>14.cookie和session的区别？</h2><ol>
<li>存在的位置：<ul>
<li>cookie存在于客户端，临时文件夹中</li>
<li>session存在于服务器的内存中，一个session域对象为一个用户浏览器服务。当访问增多，会比较占用你服务器的性能，考虑到减轻服务器性能方面，应当使用cookie。</li>
</ul>
</li>
<li>安全性<ul>
<li>cookie是以明文的方式存放在客户端的，安全性低，可以通过一个加密算法进行加密后存放</li>
<li>session存放于服务器的内存中，所以安全性好</li>
</ul>
</li>
<li>生命周期(以20分钟为例)<ul>
<li>cookie的生命周期是累计的，从创建时，就开始计时，20分钟后，cookie生命周期结束</li>
<li>session的生命周期是间隔的，从创建时，开始计时如在20分钟，没有访问session，那么session生命周期被销毁。但是，如果在20分钟内（如在第19分钟时）访问过session，那么，将重新计算session的生命周期</li>
<li>服务器关机会造成session生命周期的结束，但是对cookie没有影响</li>
</ul>
</li>
<li>访问范围<ul>
<li>session为一个用户浏览器独享</li>
<li>cookie为多个用户浏览器共享</li>
</ul>
</li>
</ol>
<h2 id="15-端口复用的作用"><a href="#15-端口复用的作用" class="headerlink" title="15.端口复用的作用"></a>15.端口复用的作用</h2><p><strong>端口复用允许在一个应用程序可以把 n 个套接字绑在一个端口上而不出错。</strong></p>
<p>设置socket的SO_REUSEADDR选项，即可实现端口复用：<br>SO_REUSEADDR可以用在以下四种情况下。 </p>
<ol>
<li>当有一个有相同本地地址和端口的socket1处于TIME_WAIT状态时，而你启动的程序的socket2要占用该地址和端口，你的程序就要用到该选项。</li>
<li>SO_REUSEADDR允许同一port上启动同一服务器的多个实例(多个进程)。但每个实例绑定的IP地址是不能相同的。在有多块网卡或用IP Alias技术的机器可以测试这种情况。</li>
<li>SO_REUSEADDR允许单个进程绑定相同的端口到多个socket上，但每个socket绑定的ip地址不同。这和2很相似，区别请看UNPv1。</li>
<li>SO_REUSEADDR允许<strong>完全相同的地址和端口的重复绑定</strong>。但这<strong>只用于UDP的多播，不用于TCP</strong>。</li>
</ol>
<h4 id="作用"><a href="#作用" class="headerlink" title="作用"></a>作用</h4><p>端口复用最常用的用途应该是防止<strong>服务器</strong>重启时之前绑定的端口还未释放或者程序突然退出而系统没有释放端口。这种情况下如果设定了端口复用，则新启动的服务器进程可以直接绑定端口。如果没有设定端口复用，绑定会失败，提示ADDR已经在使用中。</p>
<p>即：当有一个有相同本地地址和端口的socket1处于TIME_WAIT状态时，而你启动的程序的socket2要占用该地址和端口，你的程序就要用到端口复用。</p>
<h2 id="16-浏览器输入URL后发生了什么？"><a href="#16-浏览器输入URL后发生了什么？" class="headerlink" title="16.浏览器输入URL后发生了什么？"></a>16.浏览器输入URL后发生了什么？</h2><ol>
<li>DNS域名解析获取IP地址<ul>
<li>先查看浏览器dns缓存中是否有域名对应的ip。</li>
<li>如果没有，则查看操作系统dns缓存中是否有对应的ip（例如windows的hosts文件）。</li>
<li>查找路由器缓存（本地dns服务器）：如果1,2步都查询无果，则需要借助网络，路由器一般都有自己的DNS缓存，将前面的请求发给路由器，查找ISP 服务商（互联网服务提供商）缓存 DNS的服务器，如果查找到IP则直接返回，没有的话继续查找。</li>
<li>递归查询：如果以上步骤还找不到，则ISP的DNS服务器就会进行递归查询，所谓递归查询就是如果主机所询问的本地域名服务器不知道被查询域名的IP地址，那么本地域名服务器就以DNS客户的身份，向其他根域名服务器继续发出查询请求报文，而不是让该主机自己进行下一步查询。</li>
<li>迭代查询：本地域名服务器采用迭代查询，它先向一个根域名服务器查询。本地域名服务器向根域名服务器的查询一般都是采用迭代查询。所谓迭代查询就是当根域名服务器收到本地域名服务器发出的查询请求报文后，告诉本地域名服务器下一步应该查询哪一个域名服务器，然后本地域名服务器自己进行后续的查询。（而不是替代本地域名服务器进行后续查询）。</li>
</ul>
</li>
<li>浏览器与目标服务器建立TCP连接（进行三次握手）</li>
<li>浏览器通过http协议向目标服务器发送请求</li>
<li>服务器处理请求</li>
<li>服务器发出一个HTML响应</li>
<li>释放TCP连接</li>
<li>浏览器解析HTML</li>
<li>浏览器布局渲染</li>
</ol>
<h2 id="17-URI和URL的区别？"><a href="#17-URI和URL的区别？" class="headerlink" title="17.URI和URL的区别？"></a>17.URI和URL的区别？</h2><h4 id="URI，是uniform-resource-identifier，统一资源标识符，用来唯一的标识一个资源。"><a href="#URI，是uniform-resource-identifier，统一资源标识符，用来唯一的标识一个资源。" class="headerlink" title="URI，是uniform resource identifier，统一资源标识符，用来唯一的标识一个资源。"></a>URI，是uniform resource identifier，统一资源标识符，用来唯一的标识一个资源。</h4><p>Web上可用的每种资源如HTML文档、图像、视频片段、程序等都是一个来URI来定位的<br>URI一般由三部组成：</p>
<ol>
<li>访问资源的命名机制</li>
<li>存放资源的主机名</li>
<li>资源自身的名称，由路径表示，着重强调于资源。</li>
</ol>
<p>（注意：这只是一般URI资源的命名方式，只要是可以唯一标识资源的都被称为URI，上面三条合在一起是URI的充分不必要条件）</p>
<p><strong>举例：</strong></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">如：https:&#x2F;&#x2F;blog.csdn.net&#x2F;qq_32595453&#x2F;article&#x2F;details&#x2F;79516787</span><br><span class="line"></span><br><span class="line">我们可以这样解释它：</span><br><span class="line"></span><br><span class="line">①这是一个可以通过https协议访问的资源，</span><br><span class="line"></span><br><span class="line">②位于主机 blog.csdn.net上，</span><br><span class="line"></span><br><span class="line">③通过“&#x2F;qq_32595453&#x2F;article&#x2F;details&#x2F;79516787”可以对该资源进行唯一标识（注意，这个不一定是完整的路径）</span><br><span class="line"></span><br><span class="line">注意：以上三点只不过是对实例的解释，以上三点并不是URI的必要条件，</span><br><span class="line">URI只是一种概念，怎样实现无所谓，只要它唯一标识一个资源就可以了。</span><br></pre></td></tr></table></figure>
<h4 id="URL是uniform-resource-locator，统一资源定位器，它是一种具体的URI，即URL可以用来标识一个资源，而且还指明了如何locate这个资源。"><a href="#URL是uniform-resource-locator，统一资源定位器，它是一种具体的URI，即URL可以用来标识一个资源，而且还指明了如何locate这个资源。" class="headerlink" title="URL是uniform resource locator，统一资源定位器，它是一种具体的URI，即URL可以用来标识一个资源，而且还指明了如何locate这个资源。"></a>URL是uniform resource locator，统一资源定位器，它是一种具体的URI，即URL可以用来标识一个资源，而且还指明了如何locate这个资源。</h4><p>URL是Internet上用来描述信息资源的字符串，主要用在各种WWW客户程序和服务器程序上，特别是著名的Mosaic。</p>
<p>采用URL可以用一种统一的格式来描述各种信息资源，包括文件、服务器的地址和目录等。URL一般由三部组成：</p>
<ol>
<li>协议(或称为服务方式)</li>
<li>存有该资源的主机IP地址(有时也包括端口号)</li>
<li>主机资源的具体地址。如目录和文件名等</li>
</ol>
<h4 id="URL和URI的区别："><a href="#URL和URI的区别：" class="headerlink" title="URL和URI的区别："></a>URL和URI的区别：</h4><p>URI和URL都定义了资源是什么，但URL还定义了该如何访问资源。<strong>URL是一种具体的URI，它是URI的一个子集</strong>，它不仅唯一标识资源，而且还提供了定位该资源的信息。URI是一种语义上的抽象概念，可以是绝对的，也可以是相对的，而URL则必须提供足够的信息来定位，是绝对的。</p>
<p><strong>只要能唯一标识资源的就是URI，在URI的基础上给出其资源的访问方式的就是URL</strong></p>
<h4 id="生活例子："><a href="#生活例子：" class="headerlink" title="生活例子："></a>生活例子：</h4><ul>
<li>对于张三，可以用身份证号：123456789来唯一标识，所以身份证号就是URI</li>
<li>但也可以用以下字符串标识张三：<ul>
<li>人类住址协议://地球/中国/浙江省/杭州市/西湖区/某大学/14号宿舍楼/525号寝/张三</li>
<li>上面的字符串就是URL，同样起到了URI的作用，而且还可以通过上面的字符串找到张三的位置</li>
</ul>
</li>
<li>所以不论是用定位的方式还是用编号的方式，我们都可以唯一确定一个人，都是URl的一种实现，而URL就是用定位的方式实现的URI。</li>
</ul>
<h2 id="18-HTTP状态码"><a href="#18-HTTP状态码" class="headerlink" title="18.HTTP状态码"></a>18.HTTP状态码</h2><p>状态代码有三位数字组成，第一个数字定义了响应的类别，共分五种类别:</p>
<p><strong>1xx：指示信息–表示请求已接收，继续处理</strong></p>
<p><strong>2xx：成功–表示请求已被成功接收、理解、接受</strong></p>
<p><strong>3xx：重定向–要完成请求必须进行更进一步的操作</strong></p>
<p><strong>4xx：客户端错误–请求有语法错误或请求无法实现</strong></p>
<p><strong>5xx：服务器端错误–服务器未能实现合法的请求</strong></p>
<p>常见状态码：</p>
<ul>
<li>200 OK                        //客户端请求成功</li>
<li>400 Bad Request               //客户端请求有语法错误，不能被服务器所理解</li>
<li>401 Unauthorized              //请求未经授权，这个状态代码必须和WWW-Authenticate报头域一起使用 </li>
<li>403 Forbidden                 //服务器收到请求，但是拒绝提供服务</li>
<li>404 Not Found                 //请求资源不存在，eg：输入了错误的URL</li>
<li>500 Internal Server Error     //服务器发生不可预期的错误</li>
<li>503 Server Unavailable        //服务器当前不能处理客户端的请求，一段时间后可能恢复正常</li>
</ul>
<p>更多状态码：<a href="http://www.runoob.com/http/http-status-codes.html" target="_blank" rel="noopener">http://www.runoob.com/http/http-status-codes.html</a></p>
<h2 id="19-UDP打洞机制"><a href="#19-UDP打洞机制" class="headerlink" title="19.UDP打洞机制"></a>19.UDP打洞机制</h2><p><strong>原因：</strong><br>路由器的NAT（网络地址转换）机制决定了内网访问外网容易,而外网访问内网困难，且不会接收来路不明的数据包</p>
<p><strong>过程：</strong><br>主要用于不同局域网的两台主机进行UDP通信，需要借助一个中间服务器。</p>
<p>例：局域网A中的主机A要和局域网B中的主机B进行通信，中间服务器为C:</p>
<ol>
<li>两台局域网主机A和B分别先和服务器C连接，服务器C获得两边的经过NAT转换的ip和端口号。</li>
<li>其中一台局域网主机A，向服务器C发送消息，告诉服务器C他要和另一台局域网主机B进行打洞，服务器C接收到消息会把A经过NAT转换的ip和端口号发给B。</li>
<li>B收到之后先给A的ip和端口发送一个消息，但是A不会收到消息，消息会被NAT丢弃，因为A不曾给B发送过消息，NAT没有注册这条通道，所以不认识B的ip和端口。然后主机B再给服务器发送个消息，让服务器告诉主机A这边已经注册好了NAT,可以进行通信。</li>
<li>主机A这时候拿到了服务器发给它的主机B经过NAT转换的ip和端口号，然后发送消息，主机B就可以进行接收了。两边就建立了一个类似洞口一样的东西，这就是UDP打洞。</li>
</ol>
<p>打洞的目的是为了告诉NAT,我要访问的IP是我”朋友”,你不能阻拦它发过来的信息。</p>
<h2 id="20-NAT实现方式"><a href="#20-NAT实现方式" class="headerlink" title="20.NAT实现方式"></a>20.NAT实现方式</h2><h4 id="1-全锥NAT（Full-Cone-NAT）"><a href="#1-全锥NAT（Full-Cone-NAT）" class="headerlink" title="1. 全锥NAT（Full Cone NAT）"></a>1. 全锥NAT（Full Cone NAT）</h4><ul>
<li>这种NAT内部的机器A连接过外网机器C后,NAT会打开一个端口.然后外网的任何发到这个打开的端口的UDP数据报都可以到达A.不管是不是C发过来的.</li>
<li>例如 A:192.168.8.100 NAT:202.100.100.100 C:292.88.88.88</li>
<li>A(192.168.8.100:5000) -&gt; NAT(202.100.100.100 : 8000) -&gt; C(292.88.88.88:2000)</li>
<li>任何发送到 NAT(202.100.100.100:8000)的数据都可以到达A(192.168.8.100:5000)</li>
</ul>
<h4 id="2-限制性锥NAT（Address-Restricted-Cone-NAT）"><a href="#2-限制性锥NAT（Address-Restricted-Cone-NAT）" class="headerlink" title="2. 限制性锥NAT（Address-Restricted Cone NAT）"></a>2. 限制性锥NAT（Address-Restricted Cone NAT）</h4><ul>
<li>这种NAT内部的机器A连接过外网的机器C后,NAT打开一个端口.然后C可以用任何端口和A通信.其他的外网机器不行.</li>
<li>例如 A:192.168.8.100 NAT:202.100.100.100 C:292.88.88.88</li>
<li>A(192.168.8.100:5000) -&gt; NAT(202.100.100.100 : 8000) -&gt; C(292.88.88.88:2000)</li>
<li>任何从C发送到 NAT(202.100.100.100:8000)的数据都可以到达A(192.168.8.100:5000)</li>
</ul>
<h4 id="3-端口限制性锥NAT（Port-Restricted-Cone-NAT）"><a href="#3-端口限制性锥NAT（Port-Restricted-Cone-NAT）" class="headerlink" title="3. 端口限制性锥NAT（Port Restricted Cone NAT）"></a>3. 端口限制性锥NAT（Port Restricted Cone NAT）</h4><ul>
<li>这种NAT内部的机器A连接过外网的机器C后,NAT打开一个端口.然后C可以用原来的端口和A通信.其他的外网机器不行.</li>
<li>例如 A:192.168.8.100 NAT:202.100.100.100 C:292.88.88.88</li>
<li>A(192.168.8.100:5000) -&gt; NAT(202.100.100.100 : 8000) -&gt; C(292.88.88.88:2000)</li>
<li>C(202.88.88.88:2000)发送到 NAT(202.100.100.100:8000)的数据都可以到达A(192.168.8.100:5000)</li>
</ul>
<h4 id="4-对称NAT（Symmetric-NAT）"><a href="#4-对称NAT（Symmetric-NAT）" class="headerlink" title="4. 对称NAT（Symmetric NAT）"></a>4. 对称NAT（Symmetric NAT）</h4><ul>
<li>在Symmetric NAT中，目标ip和端口则成为了NAT设备建立转换关系的一个重要考量：只有来自于同一个内部ip和端口、且针对同一目标ip和端口的请求才被NAT转换至同一个外部ip和端口，否则的话，NAT将为之分配一个新的外部ip和端口；</li>
<li>打个比方，当内部主机以相同的内部ip和端口对2个不同的目标ip和端口发送UDP报文时，此时NAT将会为内部主机分配两个不同的外部ip和端口，并且建立起两个不同的内、外部 ip和端口转换关系。</li>
<li>与此同时，只有接收到了内部主机所发送的数据包的外部主机才能向内部主机返回UDP报文，这里对外部返回报文来源的限制是与Port Restricted Cone一致的。</li>
</ul>
<h2 id="21-Nagle算法"><a href="#21-Nagle算法" class="headerlink" title="21.Nagle算法"></a>21.Nagle算法</h2><h4 id="问题描述"><a href="#问题描述" class="headerlink" title="问题描述"></a>问题描述</h4><p>如果我们的应用程序一次产生1个字节的数据，而这个1个字节数据又以网络数据包的形式发送到远端服务器，那么就很容易导致网络由于太多的数据包而过载。比如，当用户使用Telnet连接到远程服务器时，每一次击键操作就会产生1个字节数据，进而发送出去一个数据包，所以，在典型情况下，传送一个只拥有1个字节有效数据的数据包，却要花费40个字节长包头（即ip头20字节+tcp头20字节）的额外开销，而且这种小包在广域网上会增加拥塞的出现，这种有效载荷（payload）利用率极其低下的情况被统称之为<strong>模糊窗口症候群（Silly Window Syndrome）</strong></p>
<h4 id="Nagle算法的改进"><a href="#Nagle算法的改进" class="headerlink" title="Nagle算法的改进"></a>Nagle算法的改进</h4><p>如果发送端欲多次发送包含少量字符的数据包（小于MSS的数据包为小包），则发送端会先将第一个小包发送出去，而将后面到达的少量字符数据都缓存起来而不立即发送，直到收到接收端对前一个数据包报文段的ACK确认、或当前字符属于紧急数据，或者积攒到了一定数量的数据（比如缓存的字符数据已经达到数据包报文段的最大长度）等多种情况才将其组成一个较大的数据包发送出去</p>
<p>Nagle算法的基本定义是<strong>任意时刻，最多只能有一个未被确认的小段</strong>。 所谓“小段”，指的是小于MSS尺寸的数据块，所谓“未被确认”，是指一个数据块发送出去后，没有收到对方发送的ACK确认该数据已收到。</p>
<h2 id="MSS和MTU的区别"><a href="#MSS和MTU的区别" class="headerlink" title="MSS和MTU的区别"></a>MSS和MTU的区别</h2><h4 id="MTU-最大传输单元-maximum-transmission-unit"><a href="#MTU-最大传输单元-maximum-transmission-unit" class="headerlink" title="MTU 最大传输单元 maximum transmission unit"></a>MTU 最大传输单元 maximum transmission unit</h4><p>物理接口（数据链路层）提供给其上层（通常是IP层）最大一次传输数据的大小；以普遍使用的以太网接口为例，缺省MTU=1500 Byte，这是以太网接口对IP层的约束，如果IP层有&lt;=1500 byte 需要发送，只需要一个IP包就可以完成发送任务；如果IP层有&gt; 1500 byte 数据需要发送，需要分片才能完成发送，这些分片有一个共同点，即IP Header ID相同。</p>
<h4 id="MSS-最大报文段长度-maximum-segment-size"><a href="#MSS-最大报文段长度-maximum-segment-size" class="headerlink" title="MSS 最大报文段长度 maximum segment size"></a>MSS 最大报文段长度 maximum segment size</h4><p>TCP提交给IP层最大数据长度，不包含TCP Header和 TCP Option，只包含TCP 有效数据 ，MSS是TCP用来限制应用层最大的发送字节数。如果底层物理接口MTU= 1500 byte，则 MSS = 1500- 20(IP Header) -20 (TCP Header) = 1460 byte，如果应用层有2000 byte发送，需要两个报文段才可以完成发送，第一个TCP segment = 1460，第二个TCP segment = 540。</p>
<p><img src="https://bkimg.cdn.bcebos.com/pic/d009b3de9c82d158ccbfd28051420ed8bc3eb135e4e3?x-bce-process=image/watermark,image_d2F0ZXIvYmFpa2U3Mg==,g_7,xp_5,yp_5" alt=""></p>
<h2 id="22-各层协议单元"><a href="#22-各层协议单元" class="headerlink" title="22.各层协议单元"></a>22.各层协议单元</h2><h4 id="物理层的协议数据单元-–-比特-bit"><a href="#物理层的协议数据单元-–-比特-bit" class="headerlink" title="物理层的协议数据单元 – 比特(bit)"></a>物理层的协议数据单元 – 比特(bit)</h4><h4 id="数据链路层的协议数据单元-–-帧"><a href="#数据链路层的协议数据单元-–-帧" class="headerlink" title="数据链路层的协议数据单元 – 帧"></a>数据链路层的协议数据单元 – 帧</h4><h4 id="网络层协议数据单元-–-IP数据报（或简称为数据报、分组或包）"><a href="#网络层协议数据单元-–-IP数据报（或简称为数据报、分组或包）" class="headerlink" title="网络层协议数据单元 – IP数据报（或简称为数据报、分组或包）"></a>网络层协议数据单元 – IP数据报（或简称为数据报、分组或包）</h4><h4 id="运输层的协议数据单元-–-TCP的报文段或UDP的用户数据报"><a href="#运输层的协议数据单元-–-TCP的报文段或UDP的用户数据报" class="headerlink" title="运输层的协议数据单元 – TCP的报文段或UDP的用户数据报"></a>运输层的协议数据单元 – TCP的报文段或UDP的用户数据报</h4><h4 id="应用层的协议数据单元-–-报文"><a href="#应用层的协议数据单元-–-报文" class="headerlink" title="应用层的协议数据单元 – 报文"></a>应用层的协议数据单元 – 报文</h4><h2 id="23-ICMP（网际控制报文协议）"><a href="#23-ICMP（网际控制报文协议）" class="headerlink" title="23.ICMP（网际控制报文协议）"></a>23.ICMP（网际控制报文协议）</h2><h4 id="ICMP差错报告报文"><a href="#ICMP差错报告报文" class="headerlink" title="ICMP差错报告报文"></a>ICMP差错报告报文</h4><ol>
<li><strong>终点不可达：</strong> 当路由器或主机不能交付数据报时就向源点发送终点不可达报文</li>
<li><strong>时间超过：</strong> 当路由器收到生存时间（TTL）为零的数据报时，除丢弃该数据报外，还有向源点发送时间超过报文。当终点在预先规定的时间内不能收到一个数据报的全部数据报片时，就把已收到的数据报片都丢弃，并向源点发送时间超过报文。</li>
<li><strong>参数问题：</strong> 当路由器或目的主机收到的数据报的首部中有的字段的值不正确时，就丢弃该数据报，并向源点发送参数问题报文。</li>
<li><strong>改变路由（重定向）：</strong> 路由器把改变路由报文发送给主机，让主机知道下次应将数据报发送给另外的路由器（可通过更好的路由）</li>
</ol>
<h4 id="ICMP询问报文"><a href="#ICMP询问报文" class="headerlink" title="ICMP询问报文"></a>ICMP询问报文</h4><ol>
<li><strong>回送请求和回答：</strong> ICMP回送请求报文是由主机或路由器向一个特定的目的主机发出的询问。收到此报文的主机必须给源主机或路由器发送ICMP回送回答报文，这种询问报文用来测试目的站是否可达以及了解其有关状态。</li>
<li><strong>时间戳请求或回答：</strong> ICMP时间戳请求报文是请某台主机或路由器回答当前的日期或时间。时间戳请求与回答报文可用于时钟同步和时间测量。</li>
</ol>
<h4 id="ICMP应用举例"><a href="#ICMP应用举例" class="headerlink" title="ICMP应用举例"></a>ICMP应用举例</h4><ol>
<li>PING，用来测试两台主机之间的连通性。PING使用了<strong>ICMP回送请求与回送回答报文</strong>。PING是应用层直接使用ICMP的一个例子。它没有经过运输层的TCP或UDP。</li>
<li>UNIX系统的traceroute，它用来跟踪一个分组从源点到终点的路径。使用的是<strong>ICMP时间超过差错报告报文</strong>。</li>
</ol>
<h2 id="24-负载均衡"><a href="#24-负载均衡" class="headerlink" title="24.负载均衡"></a>24.负载均衡</h2><h3 id="定义"><a href="#定义" class="headerlink" title="定义"></a>定义</h3><p>把负载压力根据某种算法合理分配到集群中的每一台计算机上，以减轻主服务器的压力，降低对主服务器的硬件和软件要求。</p>
<h3 id="方式"><a href="#方式" class="headerlink" title="方式"></a>方式</h3><h4 id="HTTP重定向负载均衡"><a href="#HTTP重定向负载均衡" class="headerlink" title="HTTP重定向负载均衡"></a>HTTP重定向负载均衡</h4><p>当用户发来请求的时候，Web服务器通过修改HTTP响应头中的Location标记来返回一个新的url，然后浏览器再继续请求这个新url，实际上就是页面重定向。通过重定向，来达到“负载均衡”的目标。</p>
<h4 id="DNS域名解析负载均衡"><a href="#DNS域名解析负载均衡" class="headerlink" title="DNS域名解析负载均衡"></a>DNS域名解析负载均衡</h4><p>DNS（Domain Name System）负责域名解析的服务，域名url实际上是服务器的别名，实际映射是一个IP地址，解析过程，就是DNS完成域名到IP的映射。而一个域名是可以配置成对应多个IP的。因此，DNS也就可以作为负载均衡服务。</p>
<h4 id="反向代理负载均衡"><a href="#反向代理负载均衡" class="headerlink" title="反向代理负载均衡"></a>反向代理负载均衡</h4><p>反向代理服务可以缓存资源以改善网站性能。实际上，在部署位置上，反向代理服务器处于Web服务器前面（这样才可能缓存Web相应，加速访问），这个位置也正好是负载均衡服务器的位置，所以大多数反向代理服务器同时提供负载均衡的功能，管理一组Web服务器，将请求根据负载均衡算法转发到不同的Web服务器上。</p>
<h3 id="负载均衡策略"><a href="#负载均衡策略" class="headerlink" title="负载均衡策略"></a>负载均衡策略</h3><ul>
<li>轮询</li>
<li>加权轮询</li>
<li>最少连接数</li>
<li>最快响应</li>
<li>Hash法</li>
</ul>
<p><img src="https://mmbiz.qpic.cn/mmbiz_png/R3InYSAIZkExW6GAOWqBTzHicQ4gZvj2pll2Ao853ZSPOPCN1QtNwQyVN5InCegZJ42Xrl7zic7wmqTs6JtsXoWg/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" alt=""></p>
<h2 id="25-子网掩码的作用？"><a href="#25-子网掩码的作用？" class="headerlink" title="25.子网掩码的作用？"></a>25.子网掩码的作用？</h2><p>子网掩码只有一个作用，就是<strong>将某个IP地址划分成网络地址和主机地址两部分</strong></p>
<p>子网掩码是一个32位地址，用于屏蔽IP地址的一部分以区别网络标识和主机标识，并说明该IP地址是在局域网上，还是在广域网上。只有网络标识相同的两台主机在无路由的情况下才能相互通信。</p>
<p>子网掩码是一个32位的2进制数， 其对应<strong>网络地址</strong>的所有位都置<strong>为1</strong>，对应于<strong>主机地址</strong>的所有位都置<strong>为0</strong>。子网掩码告知路由器，地址的哪一部分是网络地址，哪一部分是主机地址，使路由器正确判断任意IP地址是否是本网段的，从而正确地进行路由。</p>
<h4 id="工作过程"><a href="#工作过程" class="headerlink" title="工作过程"></a>工作过程</h4><p>子网掩码工作过程是：将32位的子网掩码与IP地址进行二进制形式的按位<strong>逻辑“与”</strong> 运算得到的便是网络地址，将子网掩码二进制<strong>按位取反</strong>，然后IP地址进行二进制的逻辑“与”（AND）运算，得到的就是主机地址。如：192.168.10.10 AND 255.255.255.0，结果为192.168.10.0，其表达的含义为：该IP地址属于 192.168.10.0这个网络，其主机号为10，即这个网络中编号为10的主机。</p>
<h4 id="子网划分"><a href="#子网划分" class="headerlink" title="子网划分"></a>子网划分</h4><p>IP地址分网络号和主机号，要将一个网络划分为多个子网，因此<strong>网络号将要占用原来的主机位</strong>，如对于一个C类地址，它用24位来标识网络号，要将其划分为2个子网则需要占用1位原来的主机标识位。此时网络号位变为25位，主机标示变为7位。同理借用2个主机位则可以将一个C类网络划分为4个子网……那计算机是怎样才知道这一网络是否划分了子网呢？这就可以从子网掩码中看出。子网掩码和IP地址一样有32bit，确定子网掩码的方法是其与IP地址中标识网络号的所有对应位都用”1”，而与主机号对应的位都是”0”。如分为2个子网的C类IP地址用25位来标识网络号，则其子网掩码为：11111111 11111111 11111111 10000000即255.255.255.128。</p>
<h4 id="—————————————-如有错误，欢迎指正！—————————————"><a href="#—————————————-如有错误，欢迎指正！—————————————" class="headerlink" title="—————————————-如有错误，欢迎指正！—————————————-"></a>—————————————-如有错误，欢迎指正！—————————————-</h4>
          
            <div class='article_footer'>
              
                
  
    
    



  

  
    
    



  

  
    
    

<section class="widget copyright  desktop mobile">
  <div class='content'>
    
      <blockquote>
        
          
            <p>本文由CyChan创作，转载请注明出处</p>

          
        
          
            <p>博客内容遵循 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 协议</p>

          
        
          
            <p>本文永久链接是：<a href=https://cychan811.gitee.io/2021/01/31/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C%E7%AC%94%E8%AE%B0/>https://cychan811.gitee.io/2021/01/31/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C%E7%AC%94%E8%AE%B0/</a></p>
          
        
      </blockquote>
    
  </div>
</section>

  

  
    
    

<section class="widget qrcode  desktop mobile">
  

  <div class='content article-entry'>
    
      
        <div class='fancybox'><img src='https://gitee.com/CyChan811/BlogImage/raw/master/img/20200704103702.png'
        
          height='128px'
        ></div>
      
    
  </div>
</section>

  


              
            </div>
          
        </div>
        
          


  <section class='meta' id="footer-meta">
    <div class='new-meta-box'>
      
        
          <div class="new-meta-item date" itemprop="dateUpdated" datetime="2021-01-31T17:33:34+08:00">
  <a class='notlink'>
    <i class="fas fa-edit fa-fw" aria-hidden="true"></i>
    <p>更新于：2021年1月31日</p>
  </a>
</div>

        
      
        
          
  
  <div class="new-meta-item meta-tags"><a class="tag" href="/tags/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C/" rel="nofollow"><i class="fas fa-hashtag fa-fw" aria-hidden="true"></i><p>计算机网络</p></a></div>


        
      
        
          

        
      
        
          
  <div class="new-meta-item share -mob-share-list">
  <div class="-mob-share-list share-body">
    
      
        <a class="-mob-share-qq" title="" rel="external nofollow noopener noreferrer"
          
          href="http://connect.qq.com/widget/shareqq/index.html?url=https://cychan811.gitee.io/2021/01/31/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C%E7%AC%94%E8%AE%B0/&title=计算机网络笔记 - CyChan's Blog&summary=1.POST和GET的区别
GET和POST本质上就是TCP链接，并无差别
GET，它用于获取信息，它只是获取、查询数据，也就是说它不会修改服务器上的数据，从这点来讲，它是数据安全的。例如获取更新的20条微博。
"
          
          >
          
            <img src="https://cdn.jsdelivr.net/gh/xaoxuu/cdn-assets/logo/128/qq.png">
          
        </a>
      
    
      
        <a class="-mob-share-qzone" title="" rel="external nofollow noopener noreferrer"
          
          href="https://sns.qzone.qq.com/cgi-bin/qzshare/cgi_qzshare_onekey?url=https://cychan811.gitee.io/2021/01/31/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C%E7%AC%94%E8%AE%B0/&title=计算机网络笔记 - CyChan's Blog&summary=1.POST和GET的区别
GET和POST本质上就是TCP链接，并无差别
GET，它用于获取信息，它只是获取、查询数据，也就是说它不会修改服务器上的数据，从这点来讲，它是数据安全的。例如获取更新的20条微博。
"
          
          >
          
            <img src="https://cdn.jsdelivr.net/gh/xaoxuu/cdn-assets/logo/128/qzone.png">
          
        </a>
      
    
      
        <a class="-mob-share-weibo" title="" rel="external nofollow noopener noreferrer"
          
          href="http://service.weibo.com/share/share.php?url=https://cychan811.gitee.io/2021/01/31/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C%E7%AC%94%E8%AE%B0/&title=计算机网络笔记 - CyChan's Blog&summary=1.POST和GET的区别
GET和POST本质上就是TCP链接，并无差别
GET，它用于获取信息，它只是获取、查询数据，也就是说它不会修改服务器上的数据，从这点来讲，它是数据安全的。例如获取更新的20条微博。
"
          
          >
          
            <img src="https://cdn.jsdelivr.net/gh/xaoxuu/cdn-assets/logo/128/weibo.png">
          
        </a>
      
    
  </div>
</div>



        
      
    </div>
  </section>


        
        
          <div class="prev-next">
            
              <a class='prev' href='/2021/01/31/mysql%E6%95%B0%E6%8D%AE%E5%BA%93%E7%AC%94%E8%AE%B0/'>
                <p class='title'><i class="fas fa-chevron-left" aria-hidden="true"></i>mysql数据库笔记</p>
                <p class='content'>1.事务的ACID特性原子性(A)一个事务要么全部提交成功，要么全部失败回滚，不能只执行其中的一部分操作，这就是事务的原子性


一致性(C)保证事务只能把数据库从一个有效（正确）的状态“转移”...</p>
              </a>
            
            
              <a class='next' href='/2021/01/31/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E7%AC%94%E8%AE%B0/'>
                <p class='title'>操作系统笔记<i class="fas fa-chevron-right" aria-hidden="true"></i></p>
                <p class='content'>1.阻塞/非阻塞IO,同步IO/异步IO，IO多路复用1. IO请求的两个阶段：

等待资源阶段：IO请求一般需要请求特殊的资源（如磁盘、RAM、文件），当资源被上一个使用者使用没有被释放时，I...</p>
              </a>
            
          </div>
        
      </section>
    </article>
  

  
    <!-- 显示推荐文章和评论 -->



  <article class="post white-box reveal comments shadow">
    <section class="article typo">
      <p ct><i class='fas fa-comments'></i> 评论</p>
      
      
      
      
      
      
        <section id="comments">
          <div id="valine_container" class="valine_thread">
            <i class="fas fa-cog fa-spin fa-fw fa-2x"></i>
          </div>
        </section>
      
      
    </section>
  </article>


  




<!-- 根据页面mathjax变量决定是否加载MathJax数学公式js -->



  <script>
    window.subData = {
      title: '计算机网络笔记',
      tools: true
    }
  </script>


</div>
<aside class='l_side'>
  
  

  
    
    



  <section class="widget toc-wrapper shadow desktop mobile" id="toc-div" >
    
  <header>
    
      <i class="fas fa-list fa-fw" aria-hidden="true"></i><span class='name'>本文目录</span>
    
  </header>


    <div class='content'>
        <ol class="toc"><li class="toc-item toc-level-2"><a class="toc-link" href="#1-POST和GET的区别"><span class="toc-text">1.POST和GET的区别</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#2-高性能网络通信库中为何要将侦听-socket-设置成非阻塞的？"><span class="toc-text">2.高性能网络通信库中为何要将侦听 socket 设置成非阻塞的？</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#3-UDP-与-TCP-比较"><span class="toc-text">3.UDP 与 TCP 比较</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#TCP："><span class="toc-text">TCP：</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#UDP："><span class="toc-text">UDP：</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#什么时候该使用TCP："><span class="toc-text">什么时候该使用TCP：</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#什么时候使用UDP："><span class="toc-text">什么时候使用UDP：</span></a></li></ol></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#4-TCP可靠传输原理"><span class="toc-text">4.TCP可靠传输原理</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#停止等待ARQ协议"><span class="toc-text">停止等待ARQ协议</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#1-无差错情况"><span class="toc-text">1. 无差错情况</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#2-出现差错"><span class="toc-text">2. 出现差错</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#3-确认丢失和确认迟到"><span class="toc-text">3. 确认丢失和确认迟到</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#流水线传输"><span class="toc-text">流水线传输</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#流水线传输："><span class="toc-text">流水线传输：</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#连续-ARQ-协议"><span class="toc-text">连续 ARQ 协议</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#累积确认"><span class="toc-text">累积确认</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#Go-back-N（回退-N）"><span class="toc-text">Go-back-N（回退 N）</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#5-TCP-拥塞控制的作用，理解具体原理"><span class="toc-text">5.TCP 拥塞控制的作用，理解具体原理</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#拥塞控制："><span class="toc-text">拥塞控制：</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#拥塞控制过程（Reno算法）"><span class="toc-text">拥塞控制过程（Reno算法）</span></a></li></ol></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#6-理解三次握手以及四次挥手具体过程，三次握手的原因、四次挥手原因"><span class="toc-text">6.理解三次握手以及四次挥手具体过程，三次握手的原因、四次挥手原因</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#三次握手过程理解："><span class="toc-text">三次握手过程理解：</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#四次挥手过程理解："><span class="toc-text">四次挥手过程理解：</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#常见面试题"><span class="toc-text">常见面试题</span></a></li></ol></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#7-TIME-WAIT的作用"><span class="toc-text">7.TIME_WAIT的作用</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#8-HTTP协议"><span class="toc-text">8.HTTP协议</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#HTTP特点"><span class="toc-text">HTTP特点</span></a></li></ol></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#9-HTTPS协议"><span class="toc-text">9.HTTPS协议</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#一般http中存在如下问题："><span class="toc-text">一般http中存在如下问题：</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#什么是HTTPS？"><span class="toc-text">什么是HTTPS？</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#浏览器在使用HTTPS传输数据的流程是什么？"><span class="toc-text">浏览器在使用HTTPS传输数据的流程是什么？</span></a></li></ol></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#10-epoll中et和lt的区别与实现原理（重要）"><span class="toc-text">10.epoll中et和lt的区别与实现原理（重要）</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#11-服务器端怎么判断客户端已断开连接"><span class="toc-text">11.服务器端怎么判断客户端已断开连接</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#12-TTL是什么？有什么用处"><span class="toc-text">12.TTL是什么？有什么用处</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#13-网络编程的一般步骤"><span class="toc-text">13.网络编程的一般步骤</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#TCP连接"><span class="toc-text">TCP连接</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#UDP连接"><span class="toc-text">UDP连接</span></a></li></ol></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#14-cookie和session的区别？"><span class="toc-text">14.cookie和session的区别？</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#15-端口复用的作用"><span class="toc-text">15.端口复用的作用</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#作用"><span class="toc-text">作用</span></a></li></ol></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#16-浏览器输入URL后发生了什么？"><span class="toc-text">16.浏览器输入URL后发生了什么？</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#17-URI和URL的区别？"><span class="toc-text">17.URI和URL的区别？</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#URI，是uniform-resource-identifier，统一资源标识符，用来唯一的标识一个资源。"><span class="toc-text">URI，是uniform resource identifier，统一资源标识符，用来唯一的标识一个资源。</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#URL是uniform-resource-locator，统一资源定位器，它是一种具体的URI，即URL可以用来标识一个资源，而且还指明了如何locate这个资源。"><span class="toc-text">URL是uniform resource locator，统一资源定位器，它是一种具体的URI，即URL可以用来标识一个资源，而且还指明了如何locate这个资源。</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#URL和URI的区别："><span class="toc-text">URL和URI的区别：</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#生活例子："><span class="toc-text">生活例子：</span></a></li></ol></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#18-HTTP状态码"><span class="toc-text">18.HTTP状态码</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#19-UDP打洞机制"><span class="toc-text">19.UDP打洞机制</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#20-NAT实现方式"><span class="toc-text">20.NAT实现方式</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#1-全锥NAT（Full-Cone-NAT）"><span class="toc-text">1. 全锥NAT（Full Cone NAT）</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#2-限制性锥NAT（Address-Restricted-Cone-NAT）"><span class="toc-text">2. 限制性锥NAT（Address-Restricted Cone NAT）</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#3-端口限制性锥NAT（Port-Restricted-Cone-NAT）"><span class="toc-text">3. 端口限制性锥NAT（Port Restricted Cone NAT）</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#4-对称NAT（Symmetric-NAT）"><span class="toc-text">4. 对称NAT（Symmetric NAT）</span></a></li></ol></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#21-Nagle算法"><span class="toc-text">21.Nagle算法</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#问题描述"><span class="toc-text">问题描述</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#Nagle算法的改进"><span class="toc-text">Nagle算法的改进</span></a></li></ol></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#MSS和MTU的区别"><span class="toc-text">MSS和MTU的区别</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#MTU-最大传输单元-maximum-transmission-unit"><span class="toc-text">MTU 最大传输单元 maximum transmission unit</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#MSS-最大报文段长度-maximum-segment-size"><span class="toc-text">MSS 最大报文段长度 maximum segment size</span></a></li></ol></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#22-各层协议单元"><span class="toc-text">22.各层协议单元</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#物理层的协议数据单元-–-比特-bit"><span class="toc-text">物理层的协议数据单元 – 比特(bit)</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#数据链路层的协议数据单元-–-帧"><span class="toc-text">数据链路层的协议数据单元 – 帧</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#网络层协议数据单元-–-IP数据报（或简称为数据报、分组或包）"><span class="toc-text">网络层协议数据单元 – IP数据报（或简称为数据报、分组或包）</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#运输层的协议数据单元-–-TCP的报文段或UDP的用户数据报"><span class="toc-text">运输层的协议数据单元 – TCP的报文段或UDP的用户数据报</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#应用层的协议数据单元-–-报文"><span class="toc-text">应用层的协议数据单元 – 报文</span></a></li></ol></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#23-ICMP（网际控制报文协议）"><span class="toc-text">23.ICMP（网际控制报文协议）</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#ICMP差错报告报文"><span class="toc-text">ICMP差错报告报文</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#ICMP询问报文"><span class="toc-text">ICMP询问报文</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#ICMP应用举例"><span class="toc-text">ICMP应用举例</span></a></li></ol></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#24-负载均衡"><span class="toc-text">24.负载均衡</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#定义"><span class="toc-text">定义</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#方式"><span class="toc-text">方式</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#HTTP重定向负载均衡"><span class="toc-text">HTTP重定向负载均衡</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#DNS域名解析负载均衡"><span class="toc-text">DNS域名解析负载均衡</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#反向代理负载均衡"><span class="toc-text">反向代理负载均衡</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#负载均衡策略"><span class="toc-text">负载均衡策略</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#25-子网掩码的作用？"><span class="toc-text">25.子网掩码的作用？</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#工作过程"><span class="toc-text">工作过程</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#子网划分"><span class="toc-text">子网划分</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#—————————————-如有错误，欢迎指正！—————————————"><span class="toc-text">—————————————-如有错误，欢迎指正！—————————————-</span></a></li></ol></li></ol></li></ol>
    </div>
  </section>


  


</aside>


  
  <footer class="clearfix">
    <br><br>
    
      
        <div class="aplayer-container">
          

  
    <meting-js
      theme='#1BCDFC'
      autoplay='false'
      volume='0.7'
      loop='all'
      order='random'
      fixed='false'
      list-max-height='340px'
      server='netease'
      type='playlist'
      id='2985312517'
      list-folded='true'>
    </meting-js>
  


        </div>
      
    
      
        <br>
        <div class="social-wrapper">
          
            
              <a href="mailto:1342736410@qq.com"
                class="social fas fa-envelope flat-btn"
                target="_blank"
                rel="external nofollow noopener noreferrer">
              </a>
            
          
            
              <a href="https://github.com/CyChan811"
                class="social fab fa-github flat-btn"
                target="_blank"
                rel="external nofollow noopener noreferrer">
              </a>
            
          
            
              <a href="http://wpa.qq.com/msgrd?v=3&amp;uin=1342736410&amp;site=qq&amp;menu=yes"
                class="social fab fa-qq flat-btn"
                target="_blank"
                rel="external nofollow noopener noreferrer">
              </a>
            
          
            
              <a href="http://music.163.com/playlist?id=2985312517&amp;userid=1980577201"
                class="social fas fa-headphones-alt flat-btn"
                target="_blank"
                rel="external nofollow noopener noreferrer">
              </a>
            
          
        </div>
      
    
      
        <div><p>博客内容遵循 <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh" target="_blank" rel="noopener">署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 协议</a></p>
        </div>
      
    
      
        本站使用
        <a href="https://volantis.js.org/" target="_blank" class="codename">volantis</a>
        作为主题，总访问量为
          <span id="busuanzi_value_site_pv"><i class="fas fa-circle-notch fa-spin fa-fw" aria-hidden="true"></i></span>
          次
      
    
      
        
      
    
      
      <br>
        <span id="timeDate"></span><span id="times"></span>
        <div class='copyright'>
          <a href="https://cychan811.gitee.io">Copyright © 2017-2020 CyChan</a>
        </div>
      
    
    
  </footer>


      <script>
      var now = new Date(); 
      function createtime() { 
          var grt= new Date("07/01/2020 12:00:00");//在此处修改你的建站时间，格式：月/日/年 时:分:秒
          now.setTime(now.getTime()+250); 
          days = (now - grt ) / 1000 / 60 / 60 / 24; dnum = Math.floor(days); 
          hours = (now - grt ) / 1000 / 60 / 60 - (24 * dnum); hnum = Math.floor(hours); 
          if(String(hnum).length ==1 ){hnum = "0" + hnum;} minutes = (now - grt ) / 1000 /60 - (24 * 60 * dnum) - (60 * hnum); 
          mnum = Math.floor(minutes); if(String(mnum).length ==1 ){mnum = "0" + mnum;} 
          seconds = (now - grt ) / 1000 - (24 * 60 * 60 * dnum) - (60 * 60 * hnum) - (60 * mnum); 
          snum = Math.round(seconds); if(String(snum).length ==1 ){snum = "0" + snum;} 
          document.getElementById("timeDate").innerHTML = "本站已安全运行 "+dnum+" 天 "+ hnum + " 小时 " + mnum + " 分 " + snum + " 秒"; 
      } 
        setInterval("createtime()",250);
     </script>
<script>setLoadingBarProgress(80);</script>


      <script>setLoadingBarProgress(60);</script>
    </div>
    <a class="s-top fas fa-arrow-up fa-fw" href='javascript:void(0)'></a>
  </div>
  
<script src="https://cdn.jsdelivr.net/npm/jquery@3.4/dist/jquery.min.js"></script>


  <script>
    
    var SEARCH_SERVICE = "hexo" || "hexo";
    var ROOT = "/" || "/";
    if (!ROOT.endsWith('/')) ROOT += '/';
  </script>





  <script async src="https://cdn.jsdelivr.net/gh/xaoxuu/cdn-volantis@2/js/instant_page.js" type="module" defer integrity="sha384-OeDn4XE77tdHo8pGtE1apMPmAipjoxUQ++eeJa6EtJCfHlvijigWiJpD7VDPWXV1"></script>


  <script src="https://cdn.jsdelivr.net/npm/scrollreveal@4.0.6/dist/scrollreveal.min.js"></script>
  <script type="text/javascript">
    $(function() {
      ScrollReveal().reveal('.l_main .reveal', {
        distance: '8px',
        duration: '800',
        interval: '100',
        scale: '1'
      });
    });
  </script>


  
<script src="https://cdn.jsdelivr.net/npm/node-waves@0.7.6/dist/waves.min.js"></script>

  <script type="text/javascript">
    $(function() {
      Waves.attach('.flat-btn', ['waves-button']);
      Waves.attach('.float-btn', ['waves-button', 'waves-float']);
      Waves.attach('.float-btn-light', ['waves-button', 'waves-float', 'waves-light']);
      Waves.attach('.flat-box', ['waves-block']);
      Waves.attach('.float-box', ['waves-block', 'waves-float']);
      Waves.attach('.waves-image');
      Waves.init();
    });
  </script>


  <script defer src="https://cdn.jsdelivr.net/gh/xaoxuu/cdn-busuanzi@2.3/js/busuanzi.pure.mini.js"></script>



  
  
  
    
<script src="https://cdn.jsdelivr.net/npm/jquery-backstretch@2.1.18/jquery.backstretch.min.js"></script>

    <script type="text/javascript">
      $(function(){
        var imgs=["https://cdn.jsdelivr.net/gh/xaoxuu/cdn-wallpaper/abstract/41F215B9-261F-48B4-80B5-4E86E165259E.jpeg", "https://cdn.jsdelivr.net/gh/xaoxuu/cdn-wallpaper/abstract/BBC19066-E176-47C2-9D22-48C81EE5DF6B.jpeg", "https://cdn.jsdelivr.net/gh/xaoxuu/cdn-wallpaper/abstract/B18FCBB3-67FD-48CC-B4F3-457BA145F17A.jpeg", "https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=3799510479,4073126189&fm=26&gp=0.jpg", "https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=2883764232,1534773763&fm=26&gp=0.jpg", "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1593783783483&di=3ad7e4713031f3e60c3a8bab2c2aae02&imgtype=0&src=http%3A%2F%2Fcz-video-photo.oss-cn-beijing.aliyuncs.com%2F20191015%2F7d47db92bbe2627ecd035976a61463cb_00001.jpg", "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1593783631802&di=0616aa53378b2de7816f786a97c75bfe&imgtype=0&src=http%3A%2F%2Fpic1.win4000.com%2Fwallpaper%2F2018-01-10%2F5a55c62f9a142.jpg", "https://cdn.jsdelivr.net/gh/xaoxuu/cdn-wallpaper/abstract/00E0F0ED-9F1C-407A-9AA6-545649D919F4.jpeg", "https://cdn.jsdelivr.net/gh/zyoushuo/Blog/images/bj1.jpg", "https://gitee.com/CyChan811/BlogImage/raw/master/img/1 (2).png", "https://gitee.com/CyChan811/BlogImage/raw/master/img/t01e2fa7120d00d62da.jpg", "https://gitee.com/CyChan811/BlogImage/raw/master/img/1 (19).jpg"];
        if ('true' == 'true') {
          function shuffle(arr){
            /*From countercurrent-time*/
            var n = arr.length;
            while(n--) {
              var index = Math.floor(Math.random() * n);
              var temp = arr[index];
              arr[index] = arr[n];
              arr[n] = temp;
            }
          }
          shuffle(imgs);
        }
        if ('') {
          $('').backstretch(
            imgs,
          {
            duration: "20000",
            fade: "1500"
          });
        } else {
          $.backstretch(
            imgs,
          {
            duration: "20000",
            fade: "1500"
          });
        }
      });
    </script>
  



  
    
<script src="https://cdn.jsdelivr.net/npm/aplayer@1.10/dist/APlayer.min.js"></script>

  
    
<script src="https://cdn.jsdelivr.net/npm/meting@2.0/dist/Meting.min.js"></script>

  









  
    
<script src="https://cdn.jsdelivr.net/gh/HCLonely/Valine@latest/dist/Valine.min.js"></script>

  
  <script>
  var GUEST_INFO = ['nick','mail','link'];
  var meta = 'nick,mail,link'.split(',').filter(function(item){
    return GUEST_INFO.indexOf(item) > -1
  });
  var REQUIRED_FIELDS = ['nick','mail','link'];
  var requiredFields = 'nick,mail'.split(',').filter(function(item){
    return REQUIRED_FIELDS.indexOf(item) > -1
  });
  var valine = new Valine();
  var master = 'f03ef4cd1728b39a2b1d24cb0c7c4ac8'.split(',');
  function emoji(path, idx, ext) {
      return path + "/" + path + "-" + idx + "." + ext;
  }
  var emojiMaps = {};
  for (var i = 1; i <= 54; i++) {
    emojiMaps['tieba-' + i] = emoji('tieba', i, 'png');
  }
  for (var i = 1; i <= 101; i++) {
    emojiMaps['qq-' + i] = emoji('qq', i, 'gif');
  }
  for (var i = 1; i <= 116; i++) {
    emojiMaps['aru-' + i] = emoji('aru', i, 'gif');
  }
  for (var i = 1; i <= 125; i++) {
    emojiMaps['twemoji-' + i] = emoji('twemoji', i, 'png');
  }
  for (var i = 1; i <= 4; i++) {
    emojiMaps['weibo-' + i] = emoji('weibo', i, 'png');
  }
  valine.init({
    el: '#valine_container',
    meta: meta,
    
    appId: "COclWTHE9FOx0Kp5LQxypRuw-gzGzoHsz",
    appKey: "IFkkcvnaeUWqUUYoWqCJ5hUY",
    placeholder: "ヾﾉ≧∀≦)o来啊，快活啊!~",
    pageSize:'10',
    avatar:'robohash',
    lang:'zh-cn',
    visitor: 'true',
    highlight: 'true',
    mathJax: 'false',
    enableQQ: 'true',
    requiredFields: requiredFields,
    emojiCDN: 'https://cdn.jsdelivr.net/gh/xaoxuu/cdn-assets/emoji/valine/',
    emojiMaps: emojiMaps,
    master: master
  })
  </script>





  
<script src="/js/app.js"></script>



  
<script src="https://cdn.jsdelivr.net/gh/xaoxuu/cdn-volantis@2.6.5/js/search.js"></script>



  
<script src="https://cdn.jsdelivr.net/gh/xaoxuu/cdn-volantis@2/js/comment_typing.js"></script>






<!-- 复制 -->

  <script src="https://cdn.jsdelivr.net/npm/clipboard@2/dist/clipboard.min.js"></script>
<script>
  function wait(callback, seconds) {
    var timelag = null;
    timelag = window.setTimeout(callback, seconds);
  }
  !function (e, t, a) {
    var initCopyCode = function(){
      var copyHtml = '';
      copyHtml += '<button class="btn-copy" data-clipboard-snippet="">';
      copyHtml += '<i class="fas fa-copy"></i><span>COPY</span>';
      copyHtml += '</button>';
      $(".highlight .code pre").before(copyHtml);
      $(".article pre code").before(copyHtml);
      var clipboard = new ClipboardJS('.btn-copy', {
        target: function(trigger) {
          return trigger.nextElementSibling;
        }
      });
      clipboard.on('success', function(e) {
        let $btn = $(e.trigger);
        $btn.addClass('copied');
        let $icon = $($btn.find('i'));
        $icon.removeClass('fa-copy');
        $icon.addClass('fa-check-circle');
        let $span = $($btn.find('span'));
        $span[0].innerText = 'COPIED';
        
        wait(function () { // 等待两秒钟后恢复
          $icon.removeClass('fa-check-circle');
          $icon.addClass('fa-copy');
          $span[0].innerText = 'COPY';
        }, 2000);
      });
      clipboard.on('error', function(e) {
        e.clearSelection();
        let $btn = $(e.trigger);
        $btn.addClass('copy-failed');
        let $icon = $($btn.find('i'));
        $icon.removeClass('fa-copy');
        $icon.addClass('fa-times-circle');
        let $span = $($btn.find('span'));
        $span[0].innerText = 'COPY FAILED';
        
        wait(function () { // 等待两秒钟后恢复
          $icon.removeClass('fa-times-circle');
          $icon.addClass('fa-copy');
          $span[0].innerText = 'COPY';
        }, 2000);
      });
    }
    initCopyCode();
  }(window, document);
</script>




<!-- fancybox -->
<script src="https://cdn.jsdelivr.net/gh/fancyapps/fancybox@3.5.7/dist/jquery.fancybox.min.js"></script>
<script>
  function pjax_fancybox() {
    $(".article-entry").find("img").not('.inline').not('a img').each(function () { //渲染 fancybox
      var element = document.createElement("a"); // a 标签
      $(element).attr("pjax-fancybox", "");  // 过滤 pjax
      $(element).attr("href", $(this).attr("src"));
      if ($(this).attr("data-original")) {
        $(element).attr("href", $(this).attr("data-original"));
      }
      $(element).attr("data-fancybox", "images");
      var caption = "";   // 描述信息
      if ($(this).attr('alt')) {  // 标准 markdown 描述信息
        $(element).attr('data-caption', $(this).attr('alt'));
        caption = $(this).attr('alt');
      }
      var div = document.createElement("div");
      $(div).addClass("fancybox");
      $(this).wrap(div); // 最外层套 div ，其实主要作用还是 class 样式
      var span = document.createElement("span");
      $(span).addClass("image-caption");
      $(span).text(caption); // 加描述
      $(this).after(span);  // 再套一层描述
      $(this).wrap(element);  // 最后套 a 标签
    })
    $(".article-entry").find("img").fancybox({
      selector: '[data-fancybox="images"]',
      hash: false,
      loop: false,
      closeClick: true,
      helpers: {
        overlay: {closeClick: true}
      },
      buttons: [
        "zoom",
        "close"
      ]
    });
  };
  $(function () {
    pjax_fancybox();
  });
</script>





  <script>setLoadingBarProgress(100);</script>
  <script src="https://cdn.jsdelivr.net/gh/zyoushuo/Blog/hexo/js/mouse_click.js"></script>
</body>
</html>
